import os
import uuid
import logging
from datetime import datetime
from pathlib import Path
from decimal import Decimal, InvalidOperation
from typing import Dict, Any, Optional

from fastapi import FastAPI, Request, Form, APIRouter, HTTPException, status
from fastapi.responses import HTMLResponse, PlainTextResponse, RedirectResponse, JSONResponse

from .utils.pay import AliPay

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("alipay-sandbox")

VIP = APIRouter()

# --------------------------
# 沙盒环境配置（直接写死当前公网域名）
# --------------------------
ALIPAY_CONFIG = {
    "appid": "9021000157659193",  # 沙箱 APPID
    # 注意：沙箱网关在回调前会主动访问此地址，如果 HTTPS 证书不被信任容易触发 502。
    # 使用 cpolar 等内网穿透时，优先选择 http，确保可达性。
    "app_notify_url": "http://233d381a.r19.cpolar.top/vip/alipay/notify",  # 公网异步通知地址
    "return_url": "http://233d381a.r19.cpolar.top/vip/pay/success",  # 公网同步回调地址
    "app_private_key_path": str(Path(__file__).resolve().parent / "keys" / "private.txt"),  # 应用私钥路径
    "alipay_public_key_path": str(Path(__file__).resolve().parent / "keys" / "public.txt"),  # 支付宝公钥路径
}

# 初始化沙盒支付宝客户端
alipay = AliPay(
    appid=ALIPAY_CONFIG["appid"],
    app_notify_url=ALIPAY_CONFIG["app_notify_url"],
    return_url=ALIPAY_CONFIG["return_url"],
    app_private_key_path=ALIPAY_CONFIG["app_private_key_path"],
    alipay_public_key_path=ALIPAY_CONFIG["alipay_public_key_path"],
    debug=True,  # 使用沙箱环境
)

# 模拟订单数据库（实际项目用MySQL等）
orders: Dict[str, Dict[str, Any]] = {}  # key: out_trade_no, value: 订单详情


# 首页：展示商品，发起支付
@VIP.get("/", response_class=HTMLResponse)
async def index(request: Request):
    html = """
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <title>VIP 支付调试</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <style>
            body { font-family: Arial, sans-serif; background:#f3f4f6; display:flex; justify-content:center; align-items:center; min-height:100vh; margin:0; }
            .card { background:#fff; padding:32px 40px; border-radius:16px; box-shadow:0 20px 40px rgba(15,23,42,0.16); width:min(420px,92vw); }
            h1 { font-size:22px; margin-top:0; color:#111827; text-align:center; }
            label { display:block; margin-top:18px; font-weight:bold; color:#1f2937; }
            input { width:100%; padding:12px 14px; border:1px solid #d1d5db; border-radius:8px; margin-top:8px; font-size:15px; }
            button { margin-top:24px; width:100%; padding:12px 16px; border:none; border-radius:10px; background:#2563eb; color:#fff; font-size:16px; font-weight:600; cursor:pointer; }
            button:hover { background:#1d4ed8; }
            .tip { margin-top:16px; font-size:13px; color:#6b7280; line-height:1.6; }
        </style>
    </head>
    <body>
        <div class="card">
            <h1>VIP 沙箱支付调试</h1>
            <form action="/vip/create_pay" method="get">
                <label for="subject">订单标题</label>
                <input id="subject" name="subject" value="VIP会员充值" required>
                <label for="amount">支付金额 (元)</label>
                <input id="amount" name="amount" type="number" step="0.01" min="0.01" value="0.01" required>
                <button type="submit">创建订单并跳转支付宝</button>
            </form>
            <p class="tip">
                成功支付后，支付宝将回调 <code>/vip/alipay/notify</code> 并跳转到 <code>/vip/pay/success</code>。
            </p>
        </div>
    </body>
    </html>
    """.strip()
    return HTMLResponse(html)


def _generate_pay_url(amount: str, subject: str) -> str:
    try:
        # 校验金额格式
        price = Decimal(amount)
        if price <= 0:
            raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="金额必须大于0")
    except (InvalidOperation, TypeError):
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="金额格式不正确")

    # 生成唯一订单号
    out_trade_no = f"TEST_{uuid.uuid4().hex[:10].upper()}"

    # 保存订单（未支付状态）
    orders[out_trade_no] = {
        "out_trade_no": out_trade_no,
        "total_amount": str(price),
        "subject": subject,
        "status": "UNPAID",
        "create_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    }
    logger.info("创建订单: %s，金额: %s元，商品: %s", out_trade_no, price, subject)

    try:
        # 生成支付的url
        query_params = alipay.direct_pay(
            subject=subject,
            out_trade_no=out_trade_no,
            total_amount=str(price),
        )
        pay_url = "https://openapi-sandbox.dl.alipaydev.com/gateway.do?{0}".format(query_params)
        logger.info("生成支付URL: %s", pay_url)  # 添加日志记录生成的支付URL
    except Exception as exc:
        logger.exception("调用支付宝下单失败: %s", exc)
        orders.pop(out_trade_no, None)
        raise HTTPException(status_code=500, detail="调用支付宝接口失败，请稍后再试")

    return pay_url


# 创建订单并跳转沙盒支付宝（POST，用于表单提交）
def _build_redirect_page(pay_url: str) -> str:
    return f"""<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>跳转支付宝</title>
    <meta http-equiv="refresh" content="0;url={pay_url}">
    <style>
        body {{ font-family: Arial, sans-serif; text-align: center; padding-top: 120px; color: #1f2937; }}
        .container {{ display: inline-block; padding: 32px 48px; border-radius: 12px; box-shadow: 0 10px 30px rgba(15,23,42,0.12); background: #fff; }}
        .spinner {{ width: 48px; height: 48px; border-radius: 50%; border: 5px solid #d1d5db; border-top-color: #2563eb; margin: 0 auto 20px; animation: spin 1s linear infinite; }}
        @keyframes spin {{ to {{ transform: rotate(360deg); }} }}
        a {{ color: #2563eb; text-decoration: none; }}
    </style>
</head>
<body>
    <div class="container">
        <div class="spinner"></div>
        <p>正在跳转至支付宝沙箱，请稍候...</p>
        <p><a href="{pay_url}" rel="noopener noreferrer">如果未自动跳转，请点击这里</a></p>
    </div>
    <script>
        setTimeout(function () {{
            window.location.replace("{pay_url}");
        }}, 200);
    </script>
</body>
</html>
"""


@VIP.post("/create_pay", response_class=HTMLResponse)
async def create_pay(
        amount: str = Form(...),  # 支付金额（如"0.01"元）
        subject: str = Form(...)  # 订单标题（如"测试商品"）
):
    pay_url = _generate_pay_url(amount, subject)
    logger.info("重定向前的支付URL: %s", pay_url)
    return HTMLResponse(content=_build_redirect_page(pay_url))


# 兼容 GET 方式，方便手动调试（?amount=0.01&subject=测试）
@VIP.get("/create_pay", response_class=HTMLResponse)
async def create_pay_get(amount: str, subject: str):
    pay_url = _generate_pay_url(amount, subject)
    logger.info("GET方式重定向前的支付URL: %s", pay_url)
    return HTMLResponse(content=_build_redirect_page(pay_url))


# 支付宝异步通知处理（沙盒会回调此接口）
@VIP.post("/alipay/notify", response_class=PlainTextResponse)
async def alipay_notify(request: Request):
    logger.info("Received notification request")
    form_data = await request.form()
    notify_params = dict(form_data)
    logger.info("收到沙盒通知: %s", notify_params)

    # 1. 验证签名
    signature = notify_params.pop("sign", None)
    logger.info("Signature from Alipay: %s", signature)
    if not signature:
        logger.warning("通知缺少签名")
        return "fail"

    is_verify = alipay.verify(notify_params, signature)
    logger.info("Signature verification result: %s", is_verify)
    if not is_verify:
        logger.warning("签名验证失败")
        return "fail"

    # 2. 验证支付状态
    trade_status = notify_params.get("trade_status")
    if trade_status != "TRADE_SUCCESS":
        logger.info(f"支付未成功: {trade_status}")
        return "success"  # 非成功状态也返回success避免重复通知

    # 3. 订单校验
    out_trade_no = notify_params["out_trade_no"]
    total_amount = notify_params.get("total_amount")

    order = orders.get(out_trade_no)
    if not order:
        logger.error("通知中的订单不存在: %s", out_trade_no)
        return "fail"

    if order["status"] == "PAID":
        logger.info("订单已支付，无需重复处理: %s", out_trade_no)
        return "success"

    if order["total_amount"] != total_amount:
        logger.error("通知金额与订单金额不一致: %s != %s", total_amount, order["total_amount"])
        return "fail"

    # 4. 更新订单状态
    order.update(
        status="PAID",
        trade_no=notify_params.get("trade_no"),
        payer_logon_id=notify_params.get("buyer_logon_id"),
        pay_time=notify_params.get("gmt_payment"),
        raw_notify=notify_params,
    )
    logger.info("订单支付成功: %s", out_trade_no)

    # TODO: 在这里添加处理VIP用户逻辑
    # 例如更新用户VIP状态、VIP有效期等

    return "success"  # 必须返回"success"


# 同步回调页面（支付后跳转）
@VIP.get("/pay/success", response_class=HTMLResponse)
async def pay_success(request: Request):
    logger.info("支付成功页面被访问，请求参数: %s", dict(request.query_params))
    params = dict(request.query_params)
    signature = params.pop("sign", None)
    is_verify = alipay.verify(params, signature) if signature else False

    out_trade_no = params.get("out_trade_no")
    trade_status = params.get("trade_status", "UNKNOWN")
    order = orders.get(out_trade_no)
    order_status = order["status"] if order else "NOT_FOUND"

    html = f"""
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <title>支付结果</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <style>
            body {{ font-family: Arial, sans-serif; background:#f8fafc; margin:0; padding:40px; }}
            .card {{ max-width:520px; margin:0 auto; background:#fff; padding:32px 40px; border-radius:16px; box-shadow:0 16px 40px rgba(15,23,42,0.12); }}
            h1 {{ margin-top:0; color:#111827; }}
            .status {{ margin:16px 0; padding:12px 16px; border-radius:10px; background:#eff6ff; color:#2563eb; }}
            dl {{ display:flex; flex-wrap:wrap; }}
            dt {{ width:150px; font-weight:600; color:#1f2937; margin-bottom:12px; }}
            dd {{ flex:1; margin:0 0 12px 0; color:#374151; }}
            .actions {{ margin-top:24px; display:flex; gap:12px; }}
            a.button {{ flex:1; text-align:center; padding:12px 0; border-radius:10px; text-decoration:none; font-weight:600; }}
            a.primary {{ background:#2563eb; color:#fff; }}
            a.secondary {{ background:#e2e8f0; color:#1f2937; }}
        </style>
    </head>
    <body>
        <div class="card">
            <h1>支付结果</h1>
            <div class="status">支付宝返回状态：{trade_status}</div>
            <dl>
                <dt>商户订单号</dt><dd>{out_trade_no or "未知"}</dd>
                <dt>验签结果</dt><dd>{"通过" if is_verify else "未通过"}</dd>
                <dt>本地订单状态</dt><dd>{order_status}</dd>
            </dl>
            <div class="actions">
                <a class="button secondary" href="/vip/">返回支付页</a>
                {"<a class='button primary' href='/vip/orders/{out_trade_no}' target='_blank'>查看订单</a>" if out_trade_no else ""}
            </div>
        </div>
    </body>
    </html>
    """.strip()
    return HTMLResponse(html)


@VIP.get("/alipay/query/{out_trade_no}")
async def query_order(out_trade_no: str):
    """
    使用查询接口获取订单签名字符串，调用方可根据需求请求支付宝网关。
    """
    try:
        signed_query = alipay.query_pay(out_trade_no)
        return {
            "gateway": "https://openapi.alipaydev.com/gateway.do",
            "query": signed_query,
        }
    except Exception as exc:
        logger.exception("查询订单失败: %s", exc)
        raise HTTPException(status_code=500, detail="查询失败，请稍后再试")


@VIP.get("/orders/{out_trade_no}")
async def get_order(out_trade_no: str):
    order = orders.get(out_trade_no)
    if not order:
        raise HTTPException(status_code=404, detail="订单不存在")
    return JSONResponse(order)


__all__ = ["VIP"]